Filter
glimpse(flights)
Observations: 336,776
Variables: 19
$ year <int> 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, 2013, ...
$ month <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ day <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ...
$ dep_time <int> 517, 533, 542, 544, 554, 554, 555, 557, 557, 558, 558,...
$ sched_dep_time <int> 515, 529, 540, 545, 600, 558, 600, 600, 600, 600, 600,...
$ dep_delay <dbl> 2, 4, 2, -1, -6, -4, -5, -3, -3, -2, -2, -2, -2, -2, -...
$ arr_time <int> 830, 850, 923, 1004, 812, 740, 913, 709, 838, 753, 849...
$ sched_arr_time <int> 819, 830, 850, 1022, 837, 728, 854, 723, 846, 745, 851...
$ arr_delay <dbl> 11, 20, 33, -18, -25, 12, 19, -14, -8, 8, -2, -3, 7, -...
$ carrier <chr> "UA", "UA", "AA", "B6", "DL", "UA", "B6", "EV", "B6", ...
$ flight <int> 1545, 1714, 1141, 725, 461, 1696, 507, 5708, 79, 301, ...
$ tailnum <chr> "N14228", "N24211", "N619AA", "N804JB", "N668DN", "N39...
$ origin <chr> "EWR", "LGA", "JFK", "JFK", "LGA", "EWR", "EWR", "LGA"...
$ dest <chr> "IAH", "IAH", "MIA", "BQN", "ATL", "ORD", "FLL", "IAD"...
$ air_time <dbl> 227, 227, 160, 183, 116, 150, 158, 53, 140, 138, 149, ...
$ distance <dbl> 1400, 1416, 1089, 1576, 762, 719, 1065, 229, 944, 733,...
$ hour <dbl> 5, 5, 5, 5, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, ...
$ minute <dbl> 15, 29, 40, 45, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, ...
$ time_hour <dttm> 2013-01-01 05:00:00, 2013-01-01 05:00:00, 2013-01-01 ...
Exercises
Find all flights that
- Had an arrival delay of two or more hours
- Flew to Houston (IAH or HOU)
- Were operated by United, American, or Delta
- Departed in summer (July, August, and September)
- Arrived more than two hours late, but didn’t leave late
- Were delayed by at least an hour, but made up over 30 minutes in flight
Departed between midnight and 6am (inclusive)
Had an arrival delay of two or more hours Since delay is in minutes, we are looking for flights where arr_delay > 120:
flights %>%
filter(arr_delay > 120)
Flew to Houston (IAH or HOU):
flights %>%
filter(dest %in% c("IAH", "HOU"))
Were operated by United, American, or Delta The variable carrier has the airline: but it is in two-digit carrier codes. However, we can look it up in the airlines dataset.
airlines
Since there are only 16 rows, its not even worth filtering. Delta is DL, American is AA, and United is UA:
filter(flights, carrier %in% c("AA", "DL", "UA"))
Departed in summer (July, August, and September) The variable month has the month, and it is numeric.
filter(flights, between(month, 7, 9))
Arrived more than two hours late, but didn’t leave late
filter(flights, !is.na(dep_delay), dep_delay <= 0, arr_delay > 120)
Were delayed by at least an hour, but made up over 30 minutes in flight
filter(flights, !is.na(dep_delay), dep_delay >= 60, arr_delay < 30)
Departed between midnight and 6am (inclusive).
filter(flights, dep_time >= 0, dep_time <= 600)
or using between (see next question)
filter(flights, between(dep_time, 0, 600))
- Another useful dplyr filtering helper is
between(). What does it do? Can you use it to simplify the code needed to answer the previous challenges?
between(x, left, right) is equivalent to x >= left & x <= right. I already used it in 1.4.
- How many flights have a missing
dep_time? What other variables are missing? What might these rows represent?
filter(flights, is.na(dep_time))
Since arr_time is also missing, these are cancelled flights.
- Why is
NA ^ 0 not missing? Why is NA | TRUE not missing? Why is FALSE & NA not missing? Can you figure out the general rule? (NA * 0 is a tricky counterexample!)
NA ^ 0 == 1 since for all numeric values \(x ^ 0 = 1\).
NA ^ 0
[1] 1
NA | TRUE is TRUE because the it doesn’t matter whether the missing value is TRUE or FALSE, x \lor T = T for all values of x.
NA | TRUE
Likewise, anything and FALSE is always FALSE.
NA & FALSE
[1] FALSE
Because the value of the missing element matters in NA | FALSE and NA & TRUE, these are missing:
NA | FALSE
[1] NA
NA & TRUE
[1] NA
wut? Since x * 0 = 0 for all \(x\) we might expect NA * 0 = 0, but that’s not the case.
NA * 0
[1] NA
Arrange
missing values always at the end.
Exercises
- How could you use
arrange() to sort all missing values to the start? (Hint: use is.na()).
This sorts by increasing dep_time, but with all missing values put first.
arrange(flights, desc(is.na(dep_time)), desc(dep_time))
- Sort flights to find the most delayed flights. Find the flights that left earliest.
The most delayed flights are found by sorting by dep_delay in descending order.
arrange(flights, desc(dep_delay))
If we sort dep_delay in ascending order, we get those that left earliest. There was a flight that left 43 minutes early.
arrange(flights, dep_delay)
- Sort flights to find the fastest flights.
I assume that by by “fastest flights” it means the flights with the minimum air time. So I sort by air_time. The fastest flights. The fastest flights area couple of flights between EWR and BDL with an air time of 20 minutes.
arrange(flights, air_time)
- Which flights travelled the longest? Which travelled the shortest?
I’ll assume hat travelled the longest or shortest refers to distance, rather than air-time.
The longest flights are the Hawaii Air (HA 51) between JFK and HNL (Honolulu) at 4,983 miles.
arrange(flights, desc(distance))
Apart from an EWR to LGA flight that was cancelled, the shortest flights are the Envoy Air Flights between EWR and PHL at 80 miles.
arrange(flights, distance)
- Brainstorm as many ways as possible to select
dep_time, dep_delay, arr_time, and arr_delay from flights.
A few ways include:
select(dep_time, dep_delay, arr_time, arr_delay)
select(starts_with("dep_"), starts_with("arr_"))
select(matches("^(dep|arr)_(time|delay)$"))
using ends_with() doesn’t work well since it would bget sched_arr_time and sched_dep_time.
- What happens if you include the name of a variable multiple times in a select() call?
It ignores the duplicates, and that variable is only included once. No error, warning, or message is emited.
select(flights, year, month, day, year, year)
- What does the
one_of() function do? Why might it be helpful in conjunction with this vector?
The one_of vector allows you to select variables with a character vector rather than as unquoted variable names. It’s useful because then you can easily pass vectors to select().
vars <- c("year", "month", "day", "dep_delay", "arr_delay")
select(flights, one_of(vars))
- Does the result of running the following code surprise you? How do the select helpers deal with case by default? How can you change that default?
select(flights, contains("TIME"))
The default behavior for contains is to ignore case. Yes, it surprises me. Upon reflection, I realized that this is likely the default behavior because dplyr is designed to deal with a variety of data backends, and some database engines don’t differentiate case.
To change the behavior add the argument ignore.case = FALSE. Now no variables are selected.
select(flights, contains("TIME", ignore.case = FALSE))
LS0tCnRpdGxlOiAiQ2ggNTogRGF0YSBUcmFuc2Zvcm1hdGlvbiIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCiMgSW50cm9kdWN0aW9uCgojIyBQcmVyZXF1aXNpdGVzCgpgYGB7cn0KbGlicmFyeShueWNmbGlnaHRzMTMpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCgojIEZpbHRlcgoKYGBge3J9CmdsaW1wc2UoZmxpZ2h0cykKYGBgCgojIyBFeGVyY2lzZXMKCjEuIEZpbmQgYWxsIGZsaWdodHMgdGhhdAoKICAxLiBIYWQgYW4gYXJyaXZhbCBkZWxheSBvZiB0d28gb3IgbW9yZSBob3VycwogIDIuIEZsZXcgdG8gSG91c3RvbiAoSUFIIG9yIEhPVSkKICAzLiBXZXJlIG9wZXJhdGVkIGJ5IFVuaXRlZCwgQW1lcmljYW4sIG9yIERlbHRhCiAgNC4gRGVwYXJ0ZWQgaW4gc3VtbWVyIChKdWx5LCBBdWd1c3QsIGFuZCBTZXB0ZW1iZXIpCiAgNS4gQXJyaXZlZCBtb3JlIHRoYW4gdHdvIGhvdXJzIGxhdGUsIGJ1dCBkaWRu4oCZdCBsZWF2ZSBsYXRlCiAgNi4gV2VyZSBkZWxheWVkIGJ5IGF0IGxlYXN0IGFuIGhvdXIsIGJ1dCBtYWRlIHVwIG92ZXIgMzAgbWludXRlcyBpbiBmbGlnaHQKICA3LiBEZXBhcnRlZCBiZXR3ZWVuIG1pZG5pZ2h0IGFuZCA2YW0gKGluY2x1c2l2ZSkKCipIYWQgYW4gYXJyaXZhbCBkZWxheSBvZiB0d28gb3IgbW9yZSBob3VycyogU2luY2UgZGVsYXkgaXMgaW4gbWludXRlcywgd2UgYXJlIGxvb2tpbmcKZm9yIGZsaWdodHMgd2hlcmUgYGFycl9kZWxheSA+IDEyMGA6CmBgYHtyfQpmbGlnaHRzICU+JSAKICBmaWx0ZXIoYXJyX2RlbGF5ID4gMTIwKQpgYGAKCipGbGV3IHRvIEhvdXN0b24gKElBSCBvciBIT1UpKjoKYGBge3J9CmZsaWdodHMgJT4lCiAgZmlsdGVyKGRlc3QgJWluJSBjKCJJQUgiLCAiSE9VIikpCmBgYAoKKldlcmUgb3BlcmF0ZWQgYnkgVW5pdGVkLCBBbWVyaWNhbiwgb3IgRGVsdGEqIFRoZSB2YXJpYWJsZSBgY2FycmllcmAgaGFzIHRoZSBhaXJsaW5lOiBidXQgaXQgaXMgaW4gdHdvLWRpZ2l0IGNhcnJpZXIgY29kZXMuIEhvd2V2ZXIsIHdlIGNhbiBsb29rIGl0IHVwIGluIHRoZSBgYWlybGluZXNgCmRhdGFzZXQuCmBgYHtyfQphaXJsaW5lcwpgYGAKU2luY2UgdGhlcmUgYXJlIG9ubHkgMTYgcm93cywgaXRzIG5vdCBldmVuIHdvcnRoIGZpbHRlcmluZy4KRGVsdGEgaXMgYERMYCwgQW1lcmljYW4gaXMgYEFBYCwgYW5kIFVuaXRlZCBpcyBgVUFgOgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGNhcnJpZXIgJWluJSBjKCJBQSIsICJETCIsICJVQSIpKQpgYGAKCipEZXBhcnRlZCBpbiBzdW1tZXIgKEp1bHksIEF1Z3VzdCwgYW5kIFNlcHRlbWJlcikqIFRoZSB2YXJpYWJsZSBgbW9udGhgIGhhcyB0aGUgbW9udGgsIGFuZCBpdCBpcyBudW1lcmljLgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGJldHdlZW4obW9udGgsIDcsIDkpKQpgYGAKCipBcnJpdmVkIG1vcmUgdGhhbiB0d28gaG91cnMgbGF0ZSwgYnV0IGRpZG7igJl0IGxlYXZlIGxhdGUqCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgIWlzLm5hKGRlcF9kZWxheSksIGRlcF9kZWxheSA8PSAwLCBhcnJfZGVsYXkgPiAxMjApCmBgYAoKKldlcmUgZGVsYXllZCBieSBhdCBsZWFzdCBhbiBob3VyLCBidXQgbWFkZSB1cCBvdmVyIDMwIG1pbnV0ZXMgaW4gZmxpZ2h0KgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsICFpcy5uYShkZXBfZGVsYXkpLCBkZXBfZGVsYXkgPj0gNjAsIGFycl9kZWxheSA8IDMwKQpgYGAKCipEZXBhcnRlZCBiZXR3ZWVuIG1pZG5pZ2h0IGFuZCA2YW0gKGluY2x1c2l2ZSkqLgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGRlcF90aW1lID49IDAsIGRlcF90aW1lIDw9IDYwMCkKYGBgCm9yIHVzaW5nIGBiZXR3ZWVuYCAoc2VlIG5leHQgcXVlc3Rpb24pCmBgYHtyfQpmaWx0ZXIoZmxpZ2h0cywgYmV0d2VlbihkZXBfdGltZSwgMCwgNjAwKSkKYGBgCgoKMi4gQW5vdGhlciB1c2VmdWwgZHBseXIgZmlsdGVyaW5nIGhlbHBlciBpcyBgYmV0d2VlbigpYC4gV2hhdCBkb2VzIGl0IGRvPyBDYW4geW91IHVzZSBpdCB0byBzaW1wbGlmeSB0aGUgY29kZSBuZWVkZWQgdG8gYW5zd2VyIHRoZSBwcmV2aW91cyBjaGFsbGVuZ2VzPwoKYGJldHdlZW4oeCwgbGVmdCwgcmlnaHQpYCBpcyBlcXVpdmFsZW50IHRvIGB4ID49IGxlZnQgJiB4IDw9IHJpZ2h0YC4gSSBhbHJlYWR5IAp1c2VkIGl0IGluIDEuNC4KCjMuIEhvdyBtYW55IGZsaWdodHMgaGF2ZSBhIG1pc3NpbmcgYGRlcF90aW1lYD8gV2hhdCBvdGhlciB2YXJpYWJsZXMgYXJlIG1pc3Npbmc/IFdoYXQgbWlnaHQgdGhlc2Ugcm93cyByZXByZXNlbnQ/CgpgYGB7cn0KZmlsdGVyKGZsaWdodHMsIGlzLm5hKGRlcF90aW1lKSkKYGBgCgpTaW5jZSBgYXJyX3RpbWVgIGlzIGFsc28gbWlzc2luZywgdGhlc2UgYXJlIGNhbmNlbGxlZCBmbGlnaHRzLgoKNC4gV2h5IGlzIGBOQSBeIDBgIG5vdCBtaXNzaW5nPyBXaHkgaXMgYE5BIHwgVFJVRWAgbm90IG1pc3Npbmc/IFdoeSBpcyBgRkFMU0UgJiBOQWAgbm90IG1pc3Npbmc/IENhbiB5b3UgZmlndXJlIG91dCB0aGUgZ2VuZXJhbCBydWxlPyAoYE5BICogMGAgaXMgYSB0cmlja3kgY291bnRlcmV4YW1wbGUhKQoKYE5BIF4gMCA9PSAxYCBzaW5jZSBmb3IgYWxsIG51bWVyaWMgdmFsdWVzICR4IF4gMCA9IDEkLiAKYGBge3J9Ck5BIF4gMApgYGAKCmBOQSB8IFRSVUVgIGlzIGBUUlVFYCBiZWNhdXNlIHRoZSBpdCBkb2Vzbid0IG1hdHRlciB3aGV0aGVyIHRoZSBtaXNzaW5nIHZhbHVlIGlzIGBUUlVFYCBvciBgRkFMU0VgLCBgeCBcbG9yIFQgPSBUYCBmb3IgYWxsIHZhbHVlcyBvZiBgeGAuCmBgYHtyfQpOQSB8IFRSVUUKYGBgCkxpa2V3aXNlLCBhbnl0aGluZyBhbmQgYEZBTFNFYCBpcyBhbHdheXMgYEZBTFNFYC4KYGBge3J9Ck5BICYgRkFMU0UKYGBgCkJlY2F1c2UgdGhlIHZhbHVlIG9mIHRoZSBtaXNzaW5nIGVsZW1lbnQgbWF0dGVycyBpbiBgTkEgfCBGQUxTRWAgYW5kIGBOQSAmIFRSVUVgLCB0aGVzZSBhcmUgbWlzc2luZzoKYGBge3J9Ck5BIHwgRkFMU0UKTkEgJiBUUlVFCmBgYAoKd3V0PyBTaW5jZSBgeCAqIDAgPSAwYCBmb3IgYWxsICR4JCB3ZSBtaWdodCBleHBlY3QgYE5BICogMCA9IDBgLCBidXQgdGhhdCdzIG5vdCB0aGUgY2FzZS4KYGBge3J9Ck5BICogMApgYGAKCiMgQXJyYW5nZQoKbWlzc2luZyB2YWx1ZXMgYWx3YXlzIGF0IHRoZSBlbmQuCgojIyBFeGVyY2lzZXMKCjEuIEhvdyBjb3VsZCB5b3UgdXNlIGBhcnJhbmdlKClgIHRvIHNvcnQgYWxsIG1pc3NpbmcgdmFsdWVzIHRvIHRoZSBzdGFydD8gKEhpbnQ6IHVzZSBgaXMubmEoKWApLgoKVGhpcyBzb3J0cyBieSBpbmNyZWFzaW5nIGBkZXBfdGltZWAsIGJ1dCB3aXRoIGFsbCBtaXNzaW5nIHZhbHVlcyBwdXQgZmlyc3QuCmBgYHtyfQphcnJhbmdlKGZsaWdodHMsIGRlc2MoaXMubmEoZGVwX3RpbWUpKSwgZGVwX3RpbWUpCmBgYAoKMi4gU29ydCBmbGlnaHRzIHRvIGZpbmQgdGhlIG1vc3QgZGVsYXllZCBmbGlnaHRzLiBGaW5kIHRoZSBmbGlnaHRzIHRoYXQgbGVmdCBlYXJsaWVzdC4KClRoZSBtb3N0IGRlbGF5ZWQgZmxpZ2h0cyBhcmUgZm91bmQgYnkgc29ydGluZyBieSBgZGVwX2RlbGF5YCBpbiBkZXNjZW5kaW5nIG9yZGVyLgpgYGB7cn0KYXJyYW5nZShmbGlnaHRzLCBkZXNjKGRlcF9kZWxheSkpCmBgYApJZiB3ZSBzb3J0IGBkZXBfZGVsYXlgIGluIGFzY2VuZGluZyBvcmRlciwgd2UgZ2V0IHRob3NlIHRoYXQgbGVmdCBlYXJsaWVzdC4KVGhlcmUgd2FzIGEgZmxpZ2h0IHRoYXQgbGVmdCA0MyBtaW51dGVzIGVhcmx5LgpgYGB7cn0KYXJyYW5nZShmbGlnaHRzLCBkZXBfZGVsYXkpCmBgYAoKMy4gU29ydCBmbGlnaHRzIHRvIGZpbmQgdGhlIGZhc3Rlc3QgZmxpZ2h0cy4KCkkgYXNzdW1lIHRoYXQgYnkgYnkgImZhc3Rlc3QgZmxpZ2h0cyIgaXQgbWVhbnMgdGhlIGZsaWdodHMgd2l0aCB0aGUgbWluaW11bSBhaXIgdGltZS4KU28gSSBzb3J0IGJ5IGBhaXJfdGltZWAuIFRoZSBmYXN0ZXN0IGZsaWdodHMuIFRoZSBmYXN0ZXN0IGZsaWdodHMgYXJlYSBjb3VwbGUgb2YgZmxpZ2h0cyBiZXR3ZWVuIEVXUiBhbmQgQkRMIHdpdGggYW4gYWlyIHRpbWUgb2YgMjAgbWludXRlcy4KYGBge3J9CmFycmFuZ2UoZmxpZ2h0cywgYWlyX3RpbWUpCmBgYAoKCjQuIFdoaWNoIGZsaWdodHMgdHJhdmVsbGVkIHRoZSBsb25nZXN0PyBXaGljaCB0cmF2ZWxsZWQgdGhlIHNob3J0ZXN0PwoKSSdsbCBhc3N1bWUgaGF0IHRyYXZlbGxlZCB0aGUgbG9uZ2VzdCBvciBzaG9ydGVzdCByZWZlcnMgdG8gZGlzdGFuY2UsIHJhdGhlciB0aGFuIGFpci10aW1lLgoKVGhlIGxvbmdlc3QgZmxpZ2h0cyBhcmUgdGhlIEhhd2FpaSBBaXIgKEhBIDUxKSBiZXR3ZWVuIEpGSyBhbmQgSE5MIChIb25vbHVsdSkgYXQgNCw5ODMgbWlsZXMuCmBgYHtyfQphcnJhbmdlKGZsaWdodHMsIGRlc2MoZGlzdGFuY2UpKQpgYGAKCkFwYXJ0IGZyb20gYW4gRVdSIHRvIExHQSBmbGlnaHQgdGhhdCB3YXMgY2FuY2VsbGVkLCB0aGUgc2hvcnRlc3QgZmxpZ2h0cyBhcmUgdGhlIEVudm95IEFpciBGbGlnaHRzIGJldHdlZW4gRVdSIGFuZCBQSEwgYXQgODAgbWlsZXMuCmBgYHtyfQphcnJhbmdlKGZsaWdodHMsIGRpc3RhbmNlKQpgYGAKCjEuIEJyYWluc3Rvcm0gYXMgbWFueSB3YXlzIGFzIHBvc3NpYmxlIHRvIHNlbGVjdCBgZGVwX3RpbWVgLCBgZGVwX2RlbGF5YCwgYGFycl90aW1lYCwgYW5kIGBhcnJfZGVsYXlgIGZyb20gZmxpZ2h0cy4KCkEgZmV3IHdheXMgaW5jbHVkZToKYGBge3J9CnNlbGVjdChkZXBfdGltZSwgZGVwX2RlbGF5LCBhcnJfdGltZSwgYXJyX2RlbGF5KQpzZWxlY3Qoc3RhcnRzX3dpdGgoImRlcF8iKSwgc3RhcnRzX3dpdGgoImFycl8iKSkKc2VsZWN0KG1hdGNoZXMoIl4oZGVwfGFycilfKHRpbWV8ZGVsYXkpJCIpKQpgYGAKdXNpbmcgYGVuZHNfd2l0aCgpYCBkb2Vzbid0IHdvcmsgd2VsbCBzaW5jZSBpdCB3b3VsZCBiZ2V0IGBzY2hlZF9hcnJfdGltZWAgYW5kIGBzY2hlZF9kZXBfdGltZWAuCgoyLiBXaGF0IGhhcHBlbnMgaWYgeW91IGluY2x1ZGUgdGhlIG5hbWUgb2YgYSB2YXJpYWJsZSBtdWx0aXBsZSB0aW1lcyBpbiBhIHNlbGVjdCgpIGNhbGw/CgpJdCBpZ25vcmVzIHRoZSBkdXBsaWNhdGVzLCBhbmQgdGhhdCB2YXJpYWJsZSBpcyBvbmx5IGluY2x1ZGVkIG9uY2UuIE5vIGVycm9yLCB3YXJuaW5nLCBvciBtZXNzYWdlIGlzIGVtaXRlZC4KYGBge3J9CnNlbGVjdChmbGlnaHRzLCB5ZWFyLCBtb250aCwgZGF5LCB5ZWFyLCB5ZWFyKQpgYGAKCjMuIFdoYXQgZG9lcyB0aGUgYG9uZV9vZigpYCBmdW5jdGlvbiBkbz8gV2h5IG1pZ2h0IGl0IGJlIGhlbHBmdWwgaW4gY29uanVuY3Rpb24gd2l0aCB0aGlzIHZlY3Rvcj8KClRoZSBgb25lX29mYCB2ZWN0b3IgYWxsb3dzIHlvdSB0byBzZWxlY3QgdmFyaWFibGVzIHdpdGggYSBjaGFyYWN0ZXIgdmVjdG9yIHJhdGhlciB0aGFuIGFzIHVucXVvdGVkIHZhcmlhYmxlIG5hbWVzLgpJdCdzIHVzZWZ1bCBiZWNhdXNlIHRoZW4geW91IGNhbiBlYXNpbHkgcGFzcyB2ZWN0b3JzIHRvIGBzZWxlY3QoKWAuCgpgYGB7cn0KdmFycyA8LSBjKCJ5ZWFyIiwgIm1vbnRoIiwgImRheSIsICJkZXBfZGVsYXkiLCAiYXJyX2RlbGF5IikKc2VsZWN0KGZsaWdodHMsIG9uZV9vZih2YXJzKSkKYGBgCgoKNC4gRG9lcyB0aGUgcmVzdWx0IG9mIHJ1bm5pbmcgdGhlIGZvbGxvd2luZyBjb2RlIHN1cnByaXNlIHlvdT8gSG93IGRvIHRoZSBzZWxlY3QgaGVscGVycyBkZWFsIHdpdGggY2FzZSBieSBkZWZhdWx0PyBIb3cgY2FuIHlvdSBjaGFuZ2UgdGhhdCBkZWZhdWx0PwoKYGBge3J9CnNlbGVjdChmbGlnaHRzLCBjb250YWlucygiVElNRSIpKQpgYGAKClRoZSBkZWZhdWx0IGJlaGF2aW9yIGZvciBjb250YWlucyBpcyB0byBpZ25vcmUgY2FzZS4KWWVzLCBpdCBzdXJwcmlzZXMgbWUuClVwb24gcmVmbGVjdGlvbiwgSSByZWFsaXplZCB0aGF0IHRoaXMgaXMgbGlrZWx5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIGJlY2F1c2UgYGRwbHlyYCBpcyBkZXNpZ25lZCB0byBkZWFsIHdpdGggYSB2YXJpZXR5IG9mIGRhdGEgYmFja2VuZHMsIGFuZCBzb21lIGRhdGFiYXNlIGVuZ2luZXMgZG9uJ3QgZGlmZmVyZW50aWF0ZSBjYXNlLgoKVG8gY2hhbmdlIHRoZSBiZWhhdmlvciBhZGQgdGhlIGFyZ3VtZW50IGBpZ25vcmUuY2FzZSA9IEZBTFNFYC4gTm93IG5vIHZhcmlhYmxlcyBhcmUgc2VsZWN0ZWQuCmBgYHtyfQpzZWxlY3QoZmxpZ2h0cywgY29udGFpbnMoIlRJTUUiLCBpZ25vcmUuY2FzZSA9IEZBTFNFKSkKYGBgCgo=